﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;
using Exec;

namespace Net
{
    public class Server:IJob
    {
        private Socket sv_socket;
        private bool loop;

        public Server()
        {
            sv_socket = new Socket(AddressFamily.InterNetwork,
                SocketType.Stream, ProtocolType.Tcp);

            IPEndPoint listenEP = new IPEndPoint(IPAddress.Any, Net.port);
            
            sv_socket.Bind(listenEP);
            sv_socket.Listen(5);

            Pool.SetReady(this);
        }

        // Aceept 쓰레드
        public void Task()
        {
            Session se;

            loop = true;
            
            while (loop)
            {
                try
                {
                    se = new Session(sv_socket.Accept());
                    Pool.SetReady(se);
                }
                catch (Exception ex) { continue; }

                
                Console.WriteLine("!" + se.GetHashCode() + " 세션 접속합니다.");
            }

            sv_socket.Close();
        }

        public void Stop()
        {
            //Client ct = new Client();

            loop = false;

            sv_socket.Close();
 
        }

        public void Shutdown()
        {

        }

        // 클라 통신 쓰레드
        private class Session:IJob
        {
            private Socket se_socket;
            private int size;
            private byte[] buf = new byte[512];
            
            private bool loop;

            public Session(Socket socket)
            {
                se_socket = socket;
            }

            public void Task()
            {
                string tn;
                loop = true;
                size = 1;

                try
                {
                    while (size > 0 && loop)
                    {
                        try
                        {
                            size = se_socket.Receive
                                (buf, 512, SocketFlags.None);
                        }
                        catch (Exception ex) { continue; }

                        if (size == 0)
                        {
                            Close();
                            continue;
                        }

                        tn = Encoding.UTF8.GetString(buf, 0, size);
                        
                        Console.WriteLine(tn);
                        Manager.Mediate(
                            new Transaction(tn)
                            );

                        try
                        {
                            se_socket.Send(buf, size, SocketFlags.None);
                        }
                        catch (Exception ex) { continue; }
                    }

                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
            }

            public void Stop()
            {
                loop = false;
                Close();
            }

            private void Close()
            {
                Console.WriteLine("!" + this.GetHashCode() + " 세션 종료합니다.");
                se_socket.Shutdown(SocketShutdown.Both);
                se_socket.Close();
            }

            public void Shutdown()
            {
            }

            /*public string GetIP()
            {
                if (se_socket.Connected)
                    return;
                return "no connected";
            }*/
        }
    }
}
